package sg.edu.nus.iss.pacman.dao;

import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreNotOpenException;

import sg.edu.nus.iss.pacman.util.IOUtils;

/**
 * An implementation class for Maze DAO with RMS.
 * 
 * @author Daniel
 *
 */
public class RmsMazeDao implements MazeDao {
	
	private RecordStore rs;

	public RmsMazeDao() {

        try
        {
            rs = RecordStore.openRecordStore("PacManMaze", true);
        }
        catch (RecordStoreException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
	}
	
	/**
	 * Deletes a Maze
     * @param name the maze name
     */
	public void deleteMaze(String name)
    {
        try
        {
        
            rs.deleteRecord(getRecordId(name));
        }
        catch (RecordStoreNotOpenException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
        catch (InvalidRecordIDException ex)
        {
            // Don't rethrow.
        }
        catch (RecordStoreException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
	}

	/**
	 * Finds Maze by name
	 * 
     * @param name the maze name
     * @return Maze or null if the maze can't be found
	 */
	public Maze findMaze(String name) {
		Maze maze = null;
		
		try {
			maze = IOUtils.convertBytesToMaze(rs.getRecord(getRecordId(name)));
		} catch (RecordStoreNotOpenException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (InvalidRecordIDException e) {
			// Don't rethrow.
		} catch (RecordStoreException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		
		return maze;
	}
	
	/**
	 * Gets record id based on maze name
	 * @param name maze name
	 * @return record id
	 */
	private int getRecordId(String name) {
		int result = -1;
		
		MazeFilter filter = new MazeFilter(name);
		try {
			RecordEnumeration re = rs.enumerateRecords(filter, null, false);
			
			while (re.hasNextElement()) {
				result = re.nextRecordId();
			}
		} catch (RecordStoreNotOpenException e) {
			e.printStackTrace();
		} catch (InvalidRecordIDException e) {
			e.printStackTrace();
		}
		
		return result;
	}
	
	

	/**
	 * Gets all Mazes
	 * 
	 * @return array of Mazes
	 */
	public Maze[] getMaze() {
		
		Maze[] maze = null;
		int i = 0;
		
		try {
			RecordEnumeration re = rs.enumerateRecords(null, null, false);
			
			if (re != null && re.hasNextElement()) {
				maze = new Maze[rs.getNumRecords()];
				
				while (re.hasNextElement()) {
					maze[i] = IOUtils.convertBytesToMaze(re.nextRecord());
					i++;
				}
				
			} else {
				maze = new Maze[]{};
			}
			
		} catch (RecordStoreNotOpenException e) {			
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (InvalidRecordIDException e) {
			// Don't re-throw.
		} catch (RecordStoreException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}
		
		return maze;
	}

	/**
	 * Saves Maze
	 * 
	 * @param maze maze
	 * @return ID 
	 */
	public int saveMaze(Maze maze) {

        int id = -1;
        try
        {
            byte[] data = IOUtils.convertMazeToBytes(maze);
            id = rs.addRecord(data, 0, data.length);
        }
        catch (RecordStoreNotOpenException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
        catch (RecordStoreException ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
        return id;
	}

}
